#include "Common.h"
#include "Posix/AppLibPosix_Msg.hpp"

#include <time.h>

/**********************************************************
 * Function Name:        AppLibPosix_MqOpen
 * Description:          创建posix 消息队列
 * Parameters[in]:       INOUT APP_LIB_POSIX_MQ_s *pstMq
 * Parameters[out]:      INOUT APP_LIB_POSIX_MQ_s *pstMq
 * ReturnValue:          ULONG
 * Author:               liuke
 * Date:                 2024.05.14
***********************************************************/
ULONG AppLibPosix_MqOpen(INOUT APP_LIB_POSIX_MQ_s *pstMq)
{
    static struct mq_attr mq_attr;
    
    memset(&mq_attr, 0, sizeof(mq_attr));
    mq_attr.mq_maxmsg = pstMq->maxmsg;
    mq_attr.mq_msgsize = pstMq->msgsize;

    pstMq->mqId = mq_open(pstMq->szMqName , O_RDWR | O_CREAT, 0666, &mq_attr);
    if (pstMq->mqId == (mqd_t)-1)
    {
        LOG_ERROR("mq_open %s fail, err: %s", pstMq->szMqName, strerror(errno));
        return STAT_ERR_POSIX_MQ_OPEN;
    }

    return STAT_SUCCESS;
}

/**********************************************************
 * Function Name:        AppLibPosix_MqClose
 * Description:          Posix消息队列关闭
 * Parameters[in]:       INOUT LIB_POSIX_MQ_s *pstMq
 * Parameters[out]:      INOUT LIB_POSIX_MQ_s *pstMq
 * ReturnValue:          ULONG
 * Author:               liuke
 * Date:                 2024.05.14
***********************************************************/
ULONG AppLibPosix_MqClose(INOUT APP_LIB_POSIX_MQ_s *pstMq)
{
    if (mq_close(pstMq->mqId) < 0)
    {
        LOG_ERROR("mq_close %s fail, err: %s", pstMq->szMqName, strerror(errno));
        return STAT_ERR_POSIX_MQ_CLOSE;
    }

    pstMq->mqId = (mqd_t)-1;
 
    return STAT_SUCCESS;
}

/**********************************************************
 * Function Name:        libPosix_MqDestory
 * Description:          Posix消息队列销毁
 * Parameters[in]:       INOUT LIB_POSIX_MQ_s *pstMq
 * Parameters[out]:      INOUT LIB_POSIX_MQ_s *pstMq
 * ReturnValue:          ULONG
 * Author:               liuke
 * Date:                 2024.05.14
***********************************************************/
ULONG AppLibPosix_MqDestory(INOUT APP_LIB_POSIX_MQ_s *pstMq)
{
    if (mq_unlink(pstMq->szMqName) < 0)
    {
        LOG_ERROR("mq_unlink %s fail, err: %s", pstMq->szMqName, strerror(errno));
        return STAT_ERR_POSIX_MQ_UNLINK;
    }
 
    return STAT_SUCCESS;
}

/**********************************************************
 * Function Name:        libPosix_MqSend
 * Description:          Posix消息队列发送
 * Parameters[in]:       IN LIB_POSIX_MQ_s *pstMq
 *                       IN LIB_POSIX_MQ_MSG_s *pstMsg
 *                       IN struct timespec *timeout
 * Parameters[out]:
 * ReturnValue:          ULONG
 * Author:               liuke
 * Date:                 2024.05.14
***********************************************************/
ULONG AppLibPosix_MqSend(IN APP_LIB_POSIX_MQ_s *pstMq, IN APP_LIB_POSIX_MQ_MSG_s *pstMsg, IN struct timespec *timeout)
{
    SINT32 iRet = 0;

    if (timeout != NULL)
    {
        iRet = mq_timedsend(pstMq->mqId, pstMsg->data, pstMsg->len, pstMsg->prio, timeout);
    }
    else
    {
        iRet = mq_send(pstMq->mqId, pstMsg->data, pstMsg->len, pstMsg->prio);
    }

    if (iRet < 0)
    {
        LOG_ERROR("mq_send %s fail, err: %s", pstMq->szMqName, strerror(errno));
        return STAT_ERR_POSIX_MQ_SEND;
    }

    return STAT_SUCCESS;
}

/**********************************************************
 * Function Name:        libPosix_MqRecv
 * Description:          Posix消息队列接收
 * Parameters[in]:       IN LIB_POSIX_MQ_s *pstMq
 *                       INOUT LIB_POSIX_MQ_MSG_s *pstMsg
 *                       IN struct timespec *timeout
 * Parameters[out]:      INOUT LIB_POSIX_MQ_MSG_s *pstMsg
 * ReturnValue:          ULONG
 * Author:               liuke
 * Date:                 2024.05.14
***********************************************************/
ULONG AppLibPosix_MqRecv(IN APP_LIB_POSIX_MQ_s *pstMq, INOUT APP_LIB_POSIX_MQ_MSG_s *pstMsg, IN struct timespec *timeout)
{
    SINT32 iRet = 0;

    if (timeout != NULL)
    {
        iRet = mq_timedreceive(pstMq->mqId, pstMsg->data, pstMsg->len, &pstMsg->prio, timeout);
    }
    else
    {
        iRet = mq_receive(pstMq->mqId, pstMsg->data, pstMsg->len, &pstMsg->prio);
    }

    if (iRet < 0)
    {
        LOG_ERROR("mq_receive %s fail, timeout %p err: %s", pstMq->szMqName, timeout, strerror(errno));
        return STAT_ERR_POSIX_MQ_RECV; 
    }

    return STAT_SUCCESS;
}

